#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>


int create_listenfd();
void handle_request(int cfd);

int main()
{

    //建立tcp连接

    int sfd = create_listenfd();


    while (1)
    {
        //接受客户端连接
        int cfd = accept(sfd,NULL,NULL);
        if (-1==cfd)
        {
            printf("服务器崩溃：%m\n");
        }else
        {
            printf("客户端链接服务器\n");
        }

        //处理客户端发送的链接
        handle_request(cfd);


    }
    return 0;
}
int create_listenfd()
{
    int sfd = socket(AF_INET,SOCK_STREAM,0);
    if (-1==sfd)
    {
        printf("创建socket失败:%m\n");
        return -1;
    }

    printf("创建socket成功\n");
    int n = 1;
    int r =  setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(n));
    if (-1==r)
    {
        printf("设置socket失败:%m\n");
        return -1;
    }
    printf("设置socket成功\n");

    struct sockaddr_in sin={0};
    sin.sin_family  =AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    sin.sin_port=htons(80);

    r = bind(sfd,(struct sockaddr*)&sin,sizeof sin);
    if (-1==r)
    {
        printf("绑定失败:%m\n");
        return -1;
    }
    printf("绑定成功\n");

    r = listen(sfd,100);

    r = bind(sfd,(struct sockaddr*)&sin,sizeof sin);
    if (-1==r)
    {
        printf("监听失败:%m\n");
        return -1;
    }
    printf("监听成功\n");


    return sfd;


}
void handle_request(int cfd)
{
    //接受请求
    char buff[1024*1024]={0};
    int nread= read(cfd,buff,1024*1024);
    printf("%d:%s\n",nread,buff);
    //解析请求
    //获取文件名
    char filename[20] = {0};
    sscanf(buff,"GET /%s",filename);
    printf("文件名:%s",filename);
    //根据文件名获取文件类型 用来放到响应头中 告诉浏览器服务器发送的是什么类型的文件
    char* mime = NULL;
    if (strstr(filename,".html"))
    {
        mime="text/html";
    }else if (strstr(filename,".jpg"))
    {
        mime="image/jpg";
    }

    //制作响应
    char response[1024*1024]={0};
    sprintf("response","HTTP/1.1 200 OK \r\n Content-Type:%s\r\n\r\n",mime);
    int headlen  = strlen(response);

    //数据
    int fd  =open(filename,O_RDONLY);
    if (-1==fd)
    {
        printf("打开文件失败:%m\n");
    }
    printf("打开文件成功\n");
    int filelen = read(fd,response+headlen,sizeof(response)-headlen);

    //发送响应
    write(cfd,response,headlen+filelen);
    close(fd);
    sleep(1);
}